<template>
  <div id="customize" class="customize">
    <tool-bar />
    <mymain />
    <div v-show="$store.state.design.shadeState" class="shade">
      <help-box />
      <save-box />
      <loading-box />
      <warm-prompt />
      <share-box />
    </div>
    <div style="visible:hidden;" v-html="fontsLoad" />
  </div>
</template>
<script>

import JSZipUtils from 'jszip-utils';
import JSZip from 'jszip';
import $ from 'jquery';
import md5 from 'js-md5';
import store from '@/store';
import mymain from './components/main';
import toolBar from './components/tool-bar';
import helpBox from './components/help-box';
import saveBox from './components/save-box';
import loadingBox from './components/loading-box';
import warmPrompt from './components/warm-prompt';
import shareBox from './components/share-box';

import svgLoader from '@/assets/svg/tools/svg-loader';
import svgToCanvas from '@/assets/svg/tools/svg-canvas';
import svgColor from '@/assets/svg/tools/svg-color';
import svgHistroy from '@/assets/svg/tools/svg-history';
import svgImage from '@/assets/svg/tools/svg-image';
import svgMatrix from '@/assets/svg/tools/svg-matrix';
import svgClip from '@/assets/svg/tools/svg-clip';
import svgEvent from '@/assets/svg/tools/svg-event';
import svgColorGroup from '@/assets/svg/tools/svg-color-group';
import svgLayer from '@/assets/svg/tools/svg-layer';

import SceneBuilder from '@/assets/bls/sceneBuilder.js';
import '@/assets/bls/babylon.objFileLoader.js';
import LightsBuilder from '@/assets/bls/lightsBuilder.js';
import { color } from '@/modelColor';
export default {
  components: {
    mymain,
    toolBar,
    helpBox,
    saveBox,
    loadingBox,
    warmPrompt,
    shareBox
  },
  data() {
    return {
      fontsLoad: '',
      model: {},
      myLoader: null
    };
  },
  created() {
    console.log(this.model);
    this.init();
    this.colorPicker();
    this.config();
    this.svgMain();
    this.main();
    this.changeImagecolor();
    this.fontLoad();
    this.txtToPic();
    console.log(this.$route.query.designId);
  },
  mounted() {
    window.parent &&
      window.parent.perLoadingHide &&
      window.parent.perLoadingHide();
    this.$store.commit('design/setSmallScreen', window.innerWidth < 1367);
    window.myTimerSpc = null;
    window.addEventListener('resize', function() {
      svgTool.cancelFun();
      myStore.commit('design/setSmallScreen', window.innerWidth < 1367);
      if (window.myTimerSpc) clearTimeout(window.myTimerSpc);
      window.myTimerSpc = setTimeout(function() {
        var dom = $('#svgbox');
        var boxW = dom.width();
        var boxH = dom.height();
        for (var k in svgTool.container) { svgTool.getRatio(svgTool.container[k], boxW, boxH); }
        window.myTimerSpc = null;
      }, 600);
    });
    window.addEventListener('mousedown', function(e) {
      if (
        myStore.state.whatTool === 3 &&
        svgTool.currentImg &&
        svgTool.currentImg.attr('imgid') === 'text'
      ) {
        // 当界面停留在编辑字体,有选中图片且选中图片是文字时,在触发取消选中事件前使cancelLate处于状态1
        svgTool.cancelLate = 1;
        setTimeout(function() {
          // 200毫秒后检查cancelLate的值如果还是处于状态1时正常触发取消选中事件并使这个值归于状态0,否则等待更换图片函数触发取消选中事件
          if (svgTool.cancelLate === 1) {
            svgTool.cancelLate = 0;
            svgTool.cancelFun();
          }
        }, 200);
      } else {
        svgTool.cancelFun();
      }
    });
  },
  methods: {
    init() {
      const BABYLON = require('babylonjs');
      console.log('BABYLON');
      console.log(BABYLON);
      var that = this;
      that.model = require(`@/assets/bls/mode${this.$route.query.designId}.js`).model;
      console.log('modeljs');
      console.log(this.model);
      console.log('modelId', window.modelId);
      console.log(that.$route.query.designId);
      if (window.modelId === undefined) {
        window.modelId = that.$route.query.designId;
      }
      window.lm = [];

      function loadRes() {
        const result = that.model.parts;
        console.log('a');
        // 加载显示
        myStore.commit('design/setCanvasLoading', true);
        console.log(result);
        if (result) {
          console.log('result');
          console.log(result);
          window.BLS.RES = result;
          const zipFile = `./res/mode${window.modelId}.zip`;
          console.log(zipFile);
          // 获取config 文件 并加载obj
          JSZipUtils.getBinaryContent(zipFile, function(err, data) {
            if (err) {
              return false;
            }
            var zip = new JSZip();
            zip.loadAsync(data).then(function(zip) {
              console.log('zip');
              console.log(zip);
              // console.log(zip.file("config.json").async("string"))
              return zip.file('config.json').async('string');
            }).then(function(config) {
              console.log('config');
              console.log(config);
              console.log($.parseJSON(config).name);
              return zip.file($.parseJSON(config).name).async('string');
            }).then(function(txt) {
              // 加载obj
              var objloader = new BABYLON.OBJFileLoader();
              console.log('txt:3d文件代码');
              BABYLON.OBJFileLoader.INVERT_Y = true;
              objloader.INVERT_Y = true;
              console.log('objloader._parseSolid(null, scene, txt, null)');
              console.log(objloader._parseSolid(null, scene, txt, null));
              return objloader._parseSolid(null, scene, txt, null);
            }).then(function(meshes) {
              console.log('meshes');
              console.log(meshes);

              scene.cameras[0].setTarget(BABYLON.Vector3.Zero());
              scene.cameras[0].setPosition(new BABYLON.Vector3(0, 0, result.camera_z));
              // scene.cameras[0].setPosition(new BABYLON.Vector3(0, 0, 20));
              scene.cameras[0].target = meshes[0].position;
              scene.cameras[0].storeState();
              // scene.cameras[0].lowerRadiusLimit = result.camera_z - 25;
              scene.cameras[0].lowerRadiusLimit = result.camera_z - 25;
              meshes.forEach(function(o) {
                // meshes 设置
                console.log('o');
                console.log(o);
                o.position.y = result.product_y;
                // o.position.y = ;
                o.rotation.z = Math.PI;
                console.log(o.position);
                // o.rotation.z = 2;

                if (o.name && o.name.toLowerCase() === 'button') {
                  console.log('等于button');
                  loader.createPBRMaterial(o.name, scene, o);
                } else {
                  console.log('不等于button ===', o.name);
                  if (!result.mtlfile[o.name]) return;
                  result.mtlfile[o.name].name = o.name;

                  loader.createStandardMaterial(o.name, scene, o, result.mtlfile[o.name]);
                }
                o.actionManager = new BABYLON.ActionManager(scene);
                o.actionManager.registerAction(action);
                o.actionManager.registerAction(action2);
                o.actionManager.registerAction(action3);
                // console.error(o.name);
              });
            }).catch(function(err) {
              console.warn(err);
            });
          });
        }
      }
      var cubeTexture; var i = 0; var action; var action2; var action3; var scene; var mouseOverUnit; var mouseOutUnit; var clickMeshEvent = null; var materiales = {}; var textures = {};
      var lastOveredMesh = null;
      var hl1 = null; var hl2;// hove 灯
      var patt = [/stitch/i, /topstitch/i, /wire/i, /Topstitch_1/i, /Topstitch_2/i];
      var svgName = {};
      //

      var isWire = function(name) {
        name = name.toLowerCase();
        var bl = false;
        patt.forEach(function(p) {
          if (p.test(name)) {
            bl = true;
          }
        });
        if (bl) {
          return true;
        } else {
          return false;
        }
      };
      var loader = {
        registerAction: function(fn) {
          // 事件注册
          if (!fn) return console.warn('注册事件无效');
          clickMeshEvent = fn;
        },
        // 获取对象资源
        getResource: function(s) {
          console.log('获取对象资源');
          console.log(s);
          // init start
          materiales = {};
          textures = {};
          svgName = {};
          // init end
          window.BLS.NotEditData = {};
          if (s) {
            scene = s;
          } else {
            scene.materials = [];
            scene.geometries = [];
            scene.meshes = [];
          }
          // mouse Over 处理
          mouseOverUnit = function(unit_mesh) {
            if (lastOveredMesh === unit_mesh.meshUnderPointer) {
              return;
            }
            hl1 = new BABYLON.HighlightLayer('hl1', scene);
            hl1.addMesh(unit_mesh.meshUnderPointer, BABYLON.Color3.Green());
            window.BLS.hl1 = hl1;
          };
          // mouse Out 处理
          mouseOutUnit = function(unit_mesh) {
            hl1.dispose();
          };
          // 创建事件
          action = new BABYLON.ExecuteCodeAction(BABYLON.ActionManager.OnPointerOverTrigger, mouseOverUnit);
          action2 = new BABYLON.ExecuteCodeAction(BABYLON.ActionManager.OnPointerOutTrigger, mouseOutUnit);
          action3 = new BABYLON.ExecuteCodeAction(BABYLON.ActionManager.OnPickTrigger, loader.mouseClickMesh);
          loader.registerAction(window.myVueApp.clikcPart);
          loadRes();
          cubeTexture = loader.createCubeTexture(scene);
        },
        // 创建一个标准的材质
        createStandardMaterial: function(materialName, scene, mesh, params) {
          if (!scene) return console.error('scene is null');
          if (!mesh) return console.error('mesh is null');
          var newMaterial = new BABYLON.StandardMaterial(materialName, scene);
          newMaterial.backFaceCulling = false;
          // 线设置
          if (isWire(params.name)) {
            mesh.isPickable = false;
            newMaterial.alpha = 0.25;
          }
          newMaterial.reflectionTexture = cubeTexture;
          newMaterial.specularColor = new BABYLON.Color3(0.0, 0.0, 0.0);
          newMaterial.invertNormalMapX = true;
          newMaterial.invertNormalMapY = true;
          newMaterial.maxSimultaneousLights = 6;

          if (params.map.image !== '') {
            // console.error()
            loader.createTexture('./res/' + params.map.image, scene, newMaterial, 'diffuseTexture');
          }
          // //法线贴图
          if (params.normalMap.image !== '') {
            loader.createTexture('./res/' + params.normalMap.image, scene, newMaterial, 'bumpTexture');
          }
          // console.log(newMaterial)
          mesh.material = newMaterial;
          // 推送SVG

          if (!materiales[params.name]) {
            materiales[params.name] = [newMaterial];
          } else {
            materiales[params.name].push(newMaterial);
          }

          if (!svgName[params.name]) {
            svgName[params.name] = true;
          } else {
            return;
          }

          svgName[params.name] = true;
          if (params.part_pic.image !== '') {
            console.log('不等于空================');
            var flag = params.part_pic.part_pic_angle === '0';

            window.svgTool.loadSvg(params.name, './res/' + params.map.image, './res/' + params.part_pic.image, flag, params.name, function(key, canvas) {
              textures[key] = new BABYLON.DynamicTexture(key, canvas, scene);
            });
          } else {
            var extName = params.map.image.split('.');
            extName = extName[extName.length - 1];
            if (extName === 'svg' && !isWire(params.name)) {
              window.svgTool.loadSvg(params.name, './res/' + params.map.image, null, false, params.name, function(key, canvas) {
                textures[key] = new BABYLON.DynamicTexture(key, canvas, scene);
                textures[key].wrapU = textures[key].wrapV = 1;
              });
            } else {
              // console.log("+++++>>>>svg 线")
              window.BLS.NotEditData[params.name] = params.map.image;
            }
          }
        },
        createPBRMaterial: function(name, scene, mesh) {
          if (!scene) return console.error('scene is null');
          if (!mesh) return console.error('mesh is null');
          var material = new BABYLON.PBRMaterial(name, scene);
          material.roughness = 2.0;
          material.metallic = 0.02;
          material.albedoColor = new BABYLON.Color3(0.99, 0.99, 0.99);
          mesh.material = material;
        },
        /**
         * 创建Texture
         * @param {*} url
         * @param {*} scene
         * @param {*} material
         * @param {*} type 类型
         */
        createTexture: function(url, scene, material, type) {
          if (!scene) return console.error('scene is null');
          if (!material) return console.error('material is null');
          i++;
          var texture = new BABYLON.Texture(url, scene, false, true, BABYLON.Texture.NEAREST_LINEAR_MIPLINEAR, function() {
            --i;
            if (i <= 0) {
              console.log('i====' + i);
              // window.BLS.Engine.hideLoadingUI();
              myStore.commit('design/setCanvasLoading', false);
            }
          });
          texture.hasAlpha = true;

          switch (type) {
            case 'diffuseTexture':
              material.diffuseTexture = texture;
              break;
            case 'bumpTexture':
              texture.level = 1.3;
              material.bumpTexture = texture;
              break;
            default:
          }
        },
        // 创建环境Texture
        createCubeTexture: function(scene) {
          if (!scene) return console.error('scene is null');
          var cubeTexture = new BABYLON.CubeTexture('/static/skybox2/skybox4', scene);
          cubeTexture.coordinatesMode = BABYLON.Texture.EQUIRECTANGULAR_MODE;
          cubeTexture.level = 0.06;
          return cubeTexture;
        },
        // 鼠标点击模型
        mouseClickMesh: function(unit_mesh) {
          hl2 = new BABYLON.HighlightLayer('hl2', scene);
          hl2.addMesh(unit_mesh.meshUnderPointer, BABYLON.Color3.Blue());
          setTimeout(function() {
            hl2.dispose();
          }, 100);
          if (!clickMeshEvent) return console.warn('事件未注册');
          clickMeshEvent(unit_mesh.meshUnderPointer.id, true);
        },
        // 更新渲染
        updateTexture: function(key) {
          console.log('更新渲染');
          console.log(key);
          if (textures[key]) {
            console.log('textures里面有key');
            console.log('textures[key]', textures[key]);
            console.log('materiales', materiales);
            console.log('materiales[key]', materiales[key]);
            materiales[key].forEach(function(v, i) {
              console.log('v', v);
              v.diffuseTexture = textures[key];
              v.diffuseTexture.update();
            });
          }
        }
      };
      this.myLoader = loader;
    },
    config() {
      // 原config.js文件
      window.globalData = {
        query: {
        //   title: 'a14c0bf1-7058-41d3-ba19-14307fe63d13',
        //   bz_edit: '0',
        //   scenee: 'shop'
        },
        count: 0,
        timer: null,
        uuid: null,
        saveObj: {},
        saveDesign: '0',
        preX: 1,
        preTimer: null
      };
      window.resourceUrl = {
      };
      var requestCount = 0;
      window.saveInServer = function(cb) {
        console.log(cb);
        saveImgAndSvg(cb);
      };
      function saveImgAndSvg(cb) {
        requestCount = 2;
        const imgSize = 500; // 导出图片尺寸
        window.BLS.saveImage(requestCount, function(base64, sn) {
          console.log('保存');
          console.log(base64);
          console.log(sn);
        }, imgSize);
      }
    },
    svgMain() {
      // 原svg-main.js文件
      function MyTool() {
        var i = 0; var len = arguments.length; var k;
        for (; i < len; i++) {
          for (k in arguments[i]) {
            if (typeof arguments[i][k] === 'function') {
              MyTool.prototype[k] = arguments[i][k];
            } else {
              this[k] = arguments[i][k];
            }
          }
        }
      }
      // 计算元素的bbox数据到dom结构上
      MyTool.prototype.computedHandle = function() {
        var w, h, x, y;
        w = this.bbox.w * this.currentSvg.ratio;
        h = this.bbox.h * this.currentSvg.ratio;
        x = this.currentSvg.startX + this.bbox.x * this.currentSvg.ratio;
        y = this.currentSvg.startY + this.bbox.y * this.currentSvg.ratio;
        myVueApp.move(w, h, x, y);
      };
      MyTool.prototype.init = function() {
        // svg-loader
        var k;
        for (k in this.container) {
          this.container[k].remove();
          this.container[k] = null;
        }
        this.container = {};
        this.currentKey = '';
        this.currentSvg = null;
        this.currentPart = null;
        this.fristTime = true;
        this.svgShowed = false;
        // svg-canvas
        for (k in this.canvasObj) this.canvasObj[k] = null;
        this.canvasObj = {};
        if (this.loopTimeout) {
          clearTimeout(this.loopTimeout);
          this.loopTimeout = null;
          svgTool.renderLoop = {};
        }
        // svg-color-group
        this.colorGroupObj = {};
        // svg-color
        this.tempPiceArr = null;
        this.tempObj = { rgb: '', pantone: '', key: '', flag: false };
        // svg-event
        this.needAddToHistory = false;
        this.loc = '';
        this.bbox = null;
        this.cancelLate = 0;
        // svg-history
        this.nowIndex = -1;
        this.historyArr = [];
        this.historyObj = null;
        // svg-image
        this.currentImg = null;
      };
      window.svgTool = new MyTool(svgLoader, svgToCanvas, svgColor, svgHistroy, svgImage, svgMatrix, svgClip, svgEvent, svgColorGroup, svgLayer);
    },
    main() {
      // 原main.js文件
      // 定义Babylon
      window.BLS = {};
      var canvas, engine, scene;
      var that = this;
      var init = function(mold_id) {
        // 事件注册
        window.BLS.rotation = SceneBuilder.rotation;
        window.BLS.updateTexture = that.myLoader.updateTexture;
        // 获取canvas
        canvas = document.getElementById('canvasbox');
        // 创建一个3D引擎
        // 引擎配置对象
        var engineConfig = {
          alpha: true,
          stencil: true,
          antialias: true,
          depth: true,
          failIfMajorPerformanceCaveat: true,
          limitDeviceRatio: window.devicePixelRatio,
          preserveDrawingBuffer: true,
          lockstepMaxSteps: 24
        };
        engine = new BABYLON.Engine(canvas, true, engineConfig, true);
        window.BLS.Engine = engine;
        engine.loadingUIText = 'Loading...';
        engine.loadingUIBackgroundColor = '#fff000';
        scene = SceneBuilder.createScene(engine, canvas);
        window.scene = scene;

        // 场景配置start
        scene.defaultCursor = 'grab';// hove 游标手形
        // 场景配置end
        // 设置背景 1白0黑
        scene.clearColor = new BABYLON.Color3(245 / 255, 247 / 255, 247 / 255);
        console.log(scene);
        console.log('配置灯光');
        // 配置灯光
        LightsBuilder.createLights(scene);
        // 渲染
        engine.runRenderLoop(function() {
          scene.render();
        });
        that.myLoader.getResource(scene);
        // 监听缩放事件
        window.addEventListener('resize', function() {
          engine.resize();
        });
        // canvas 大小变化
        window.BLS.resize = function() {
          console.log('resize');
          engine.resize();
        };
        //
      };
      // 保存图片方法
      window.BLS.saveImage = function(num, cb, size) {
        // 保存效果图片
        var tw = canvas.width; var th = canvas.height;
        canvas.width = size || 800;
        canvas.height = size || 800;
        window.BLS.hl1 && window.BLS.hl1.dispose();
        //
        window.BLS.camera.restoreState();
        if (num <= 0) return;
        var count = 0;
        scene.registerAfterRender(function() {
          if (count++ < num) {
            window.BLS.camera.alpha = 2 * Math.PI * (count / num + 0.25);
            BABYLON.Tools.CreateScreenshot(engine, window.BLS.camera, size || 800, function(data) {
              if (cb) {
                cb(data, count);
              }
            });
          }
          if (count === num) {
            canvas.width = tw;
            canvas.height = th;
          }
        });

        //  console.log(i);
      };
      window.BLS.init = init;
      window.BLS.getResourceById = function(mold_id) {
        if (!mold_id) return;
        if (!window.resourceUrl.getMoldById) return;
        this.myLoader.getResource();
      };
    },
    changeImagecolor() {
      var myCanvas = document.createElement('canvas');
      var maxSize = 500;
      var myCtx; var imgData = null;

      myCanvas.width = maxSize;
      myCanvas.height = maxSize;
      myCanvas.style.width = maxSize + 'px';
      myCanvas.style.height = maxSize + 'px';
      myCtx = myCanvas.getContext('2d');

      window.changeCommonImageColor = function changeCommonImageColor(url, color, cb, commonG) {
        var myImg = document.createElement('img');
        myImg.crossOrigin = true;
        myImg.src = url;
        myImg.onload = function(e) {
          imgLoad.bind(this)(color, cb, commonG);
        };
        myImg.onerror = imgError;
      };

      function imgLoad(color, cb, commonG) {
        myCtx.clearRect(0, 0, maxSize, maxSize);
        myCtx.drawImage(this, 0, 0, maxSize, maxSize);
        imgData = myCtx.getImageData(0, 0, maxSize, maxSize);
        var i = 0; var len = imgData.data.length;
        for (i; i < len; i += 4) {
          imgData.data[i] = color[0];
          imgData.data[i + 1] = color[1];
          imgData.data[i + 2] = color[2];
        }
        myCtx.putImageData(imgData, 0, 0);
        imgData = null;
        cb && cb(myCanvas.toDataURL(), color, commonG);
      }

      function imgError(e) {
        alert('Failed to load picture');
      }
    },
    fontLoad() {
      // 加载字体文件
      const fontsArray = this.model.fontsArr.data.fonts;
      var fontsLoadStr = '';
      for (var key in fontsArray) {
        console.log(fontsArray[key]);
        fontsLoadStr += `<i style="font-family:${fontsArray[key].fullname}"></i>`;
      }
      this.fontsLoad = fontsLoadStr;
    },
    txtToPic() {
      // 注册文字生成图片方法
      var myStore = store;
      // 文字生成图片
      var that = this;
      window.getFontPic = function(obj, cb) {
        console.log(that);
        console.log('add text');
        console.log(obj);
        console.log(cb);
        var myArr = [myStore.state.design.salt]; var myObj = {};
        for (var k in obj) {
          myArr.push(obj[k]);
          myObj[k] = obj[k];
        }
        myObj.signature = md5(myArr.sort().join(''));
        console.log('myObj');
        console.log(myObj);

        // 前端文字生成图片--begin
        const span = document.createElement('span');
        console.log(span);
        const textNode = document.createTextNode(myObj.txt);
        span.appendChild(textNode);
        console.log(that.model.fontsArr);
        console.log(~~myObj.font);
        const fontFamily = that.model.fontsArr.data.fonts[~~myObj.font].fullname;
        console.log('fontFamily = ' + fontFamily);
        span.style.fontSize = '120px';
        span.style.lineHeight = '120px';
        span.style.fontFamily = fontFamily;
        // span.style.visibility = 'hidden';
        document.getElementById('customize').appendChild(span);
        const width = span.offsetWidth + myObj.strokewidth * 2;
        const height = span.offsetHeight;
        document.getElementById('customize').removeChild(span);

        const canvas = document.createElement('canvas');
        canvas.setAttribute('style', 'background: transparent;');
        canvas.setAttribute('id', 'canvas');
        canvas.setAttribute('width', width);
        canvas.setAttribute('height', height);
        document.getElementById('customize').appendChild(canvas);
        var context = document.getElementById('canvas').getContext('2d');
        // 字体
        context.font = `120px ${fontFamily}`;
        // 描边Width
        context.lineWidth = myObj.strokewidth;
        // 描边颜色
        context.strokeStyle = `#${myObj.stroke}`;
        // 设置文字颜色
        context.fillStyle = `#${myObj.fill_color}`;
        // 绘制描边
        context.strokeText(myObj.txt, myObj.strokewidth, height / 2 + (height - 120) / 2 + ~~myObj.strokewidth);
        // 绘制文字
        context.fillText(myObj.txt, myObj.strokewidth, height / 2 + (height - 120) / 2 + ~~myObj.strokewidth);
        console.log('图片地址', canvas.toDataURL('image/png'));
        cb && cb(canvas.toDataURL('image/png'));
        document.getElementById('customize').removeChild(canvas);
      };
      var colorData = color; var k; var i;
      colorData['Cool Gray10C'][8] = { rgb: '000033', pantone: 'Black 6C' };
      for (k in colorData) for (i = 0; i < colorData[k].length; i++) myStore.commit('design/addPantoneData', colorData[k][i]);

      window.setProduct = function(title, flag) {
        window.myStore.commit('setTitle', title);
        if (flag) window.myStore.commit('setShadeState', 4);
      };
      window.myVueApp = {};
      window.myStore = myStore;
    },
    colorPicker() {
      (function($) {
        var ColorPicker = (function() {
          var charMin = 65;
          var tpl = '<div class="colorpicker"><div class="colorpicker_color"><div><div></div></div></div><div class="colorpicker_hue"><div></div></div><div class="colorpicker_new_color"></div><div class="colorpicker_current_color"></div><div class="colorpicker_hex"><input type="text" maxlength="6" size="6" /></div><div class="colorpicker_rgb_r colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_rgb_g colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_rgb_b colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_hsb_h colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_hsb_s colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_hsb_b colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_submit"></div></div>';
          var defaults = {
            eventName: 'click',
            onShow: function() {},
            onBeforeShow: function() {},
            onHide: function() {},
            onChange: function() {},
            onSubmit: function() {},
            color: 'ff0000',
            livePreview: true,
            flat: false
          };
          var fillRGBFields = function(hsb, cal) {
            var rgb = HSBToRGB(hsb);
            $(cal).data('colorpicker').fields
              .eq(1).val(rgb.r).end()
              .eq(2).val(rgb.g).end()
              .eq(3).val(rgb.b).end();
          };
          var fillHSBFields = function(hsb, cal) {
            $(cal).data('colorpicker').fields
              .eq(4).val(hsb.h).end()
              .eq(5).val(hsb.s).end()
              .eq(6).val(hsb.b).end();
          };
          var fillHexFields = function(hsb, cal) {
            $(cal).data('colorpicker').fields
              .eq(0).val(HSBToHex(hsb)).end();
          };
          var setSelector = function(hsb, cal) {
            $(cal).data('colorpicker').selector.css('backgroundColor', '#' + HSBToHex({ h: hsb.h, s: 100, b: 100 }));
            $(cal).data('colorpicker').selectorIndic.css({
              left: parseInt(150 * hsb.s / 100, 10),
              top: parseInt(150 * (100 - hsb.b) / 100, 10)
            });
          };
          var setHue = function(hsb, cal) {
            $(cal).data('colorpicker').hue.css('top', parseInt(150 - 150 * hsb.h / 360, 10));
          };
          var setCurrentColor = function(hsb, cal) {
            $(cal).data('colorpicker').currentColor.css('backgroundColor', '#' + HSBToHex(hsb));
          };
          var setNewColor = function(hsb, cal) {
            $(cal).data('colorpicker').newColor.css('backgroundColor', '#' + HSBToHex(hsb));
          };
          var keyDown = function(ev) {
            var pressedKey = ev.charCode || ev.keyCode || -1;
            if ((pressedKey > charMin && pressedKey <= 90) || pressedKey === 32) {
              return false;
            }
            var cal = $(this).parent().parent();
            if (cal.data('colorpicker').livePreview === true) {
              change.apply(this);
            }
          };
          var change = function(ev) {
            var cal = $(this).parent().parent(); var col;
            if (this.parentNode.className.indexOf('_hex') > 0) {
              cal.data('colorpicker').color = col = HexToHSB(fixHex(this.value));
            } else if (this.parentNode.className.indexOf('_hsb') > 0) {
              cal.data('colorpicker').color = col = fixHSB({
                h: parseInt(cal.data('colorpicker').fields.eq(4).val(), 10),
                s: parseInt(cal.data('colorpicker').fields.eq(5).val(), 10),
                b: parseInt(cal.data('colorpicker').fields.eq(6).val(), 10)
              });
            } else {
              cal.data('colorpicker').color = col = RGBToHSB(fixRGB({
                r: parseInt(cal.data('colorpicker').fields.eq(1).val(), 10),
                g: parseInt(cal.data('colorpicker').fields.eq(2).val(), 10),
                b: parseInt(cal.data('colorpicker').fields.eq(3).val(), 10)
              }));
            }
            if (ev) {
              fillRGBFields(col, cal.get(0));
              fillHexFields(col, cal.get(0));
              fillHSBFields(col, cal.get(0));
            }
            setSelector(col, cal.get(0));
            setHue(col, cal.get(0));
            setNewColor(col, cal.get(0));
            cal.data('colorpicker').onChange.apply(cal, [col, HSBToHex(col), HSBToRGB(col)]);
          };
          var blur = function(ev) {
            var cal = $(this).parent().parent();
            cal.data('colorpicker').fields.parent().removeClass('colorpicker_focus');
          };
          var focus = function() {
            charMin = this.parentNode.className.indexOf('_hex') > 0 ? 70 : 65;
            $(this).parent().parent().data('colorpicker').fields.parent().removeClass('colorpicker_focus');
            $(this).parent().addClass('colorpicker_focus');
          };
          var downIncrement = function(ev) {
            var field = $(this).parent().find('input').focus();
            var current = {
              el: $(this).parent().addClass('colorpicker_slider'),
              max: this.parentNode.className.indexOf('_hsb_h') > 0 ? 360 : (this.parentNode.className.indexOf('_hsb') > 0 ? 100 : 255),
              y: ev.pageY,
              field: field,
              val: parseInt(field.val(), 10),
              preview: $(this).parent().parent().data('colorpicker').livePreview
            };
            $(document).bind('mouseup', current, upIncrement);
            $(document).bind('mousemove', current, moveIncrement);
          };
          var moveIncrement = function(ev) {
            ev.data.field.val(Math.max(0, Math.min(ev.data.max, parseInt(ev.data.val + ev.pageY - ev.data.y, 10))));
            if (ev.data.preview) {
              change.apply(ev.data.field.get(0), [true]);
            }
            return false;
          };
          var upIncrement = function(ev) {
            change.apply(ev.data.field.get(0), [true]);
            ev.data.el.removeClass('colorpicker_slider').find('input').focus();
            $(document).unbind('mouseup', upIncrement);
            $(document).unbind('mousemove', moveIncrement);
            return false;
          };
          var downHue = function(ev) {
            var current = {
              cal: $(this).parent(),
              y: $(this).offset().top
            };
            current.preview = current.cal.data('colorpicker').livePreview;
            $(document).bind('mouseup', current, upHue);
            $(document).bind('mousemove', current, moveHue);
          };
          var moveHue = function(ev) {
            change.apply(
              ev.data.cal.data('colorpicker')
                .fields
                .eq(4)
                .val(parseInt(360 * (150 - Math.max(0, Math.min(150, (ev.pageY - ev.data.y)))) / 150, 10))
                .get(0),
              [ev.data.preview]
            );
            return false;
          };
          var upHue = function(ev) {
            fillRGBFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0));
            fillHexFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0));
            $(document).unbind('mouseup', upHue);
            $(document).unbind('mousemove', moveHue);
            return false;
          };
          var downSelector = function(ev) {
            var current = {
              cal: $(this).parent(),
              pos: $(this).offset()
            };
            current.preview = current.cal.data('colorpicker').livePreview;
            $(document).bind('mouseup', current, upSelector);
            $(document).bind('mousemove', current, moveSelector);
          };
          var moveSelector = function(ev) {
            change.apply(
              ev.data.cal.data('colorpicker')
                .fields
                .eq(6)
                .val(parseInt(100 * (150 - Math.max(0, Math.min(150, (ev.pageY - ev.data.pos.top)))) / 150, 10))
                .end()
                .eq(5)
                .val(parseInt(100 * (Math.max(0, Math.min(150, (ev.pageX - ev.data.pos.left)))) / 150, 10))
                .get(0),
              [ev.data.preview]
            );
            return false;
          };
          var upSelector = function(ev) {
            fillRGBFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0));
            fillHexFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0));
            $(document).unbind('mouseup', upSelector);
            $(document).unbind('mousemove', moveSelector);
            return false;
          };
          var enterSubmit = function(ev) {
            $(this).addClass('colorpicker_focus');
          };
          var leaveSubmit = function(ev) {
            $(this).removeClass('colorpicker_focus');
          };
          var clickSubmit = function(ev) {
            var cal = $(this).parent();
            var col = cal.data('colorpicker').color;
            cal.data('colorpicker').origColor = col;
            setCurrentColor(col, cal.get(0));
            cal.data('colorpicker').onSubmit(col, HSBToHex(col), HSBToRGB(col), cal.data('colorpicker').el);
          };
          var show = function(ev) {
            var cal = $('#' + $(this).data('colorpickerId'));
            cal.data('colorpicker').onBeforeShow.apply(this, [cal.get(0)]);
            var pos = $(this).offset();
            var viewPort = getViewport();
            var top = pos.top + this.offsetHeight;
            var left = pos.left;
            if (top + 176 > viewPort.t + viewPort.h) {
              top -= this.offsetHeight + 176;
            }
            if (left + 356 > viewPort.l + viewPort.w) {
              left -= 356;
            }
            cal.css({ left: left + 'px', top: top + 'px' });
            if (cal.data('colorpicker').onShow.apply(this, [cal.get(0)]) !== false) {
              cal.show();
            }
            $(document).bind('mousedown', { cal: cal }, hide);
            return false;
          };
          var hide = function(ev) {
            if (!isChildOf(ev.data.cal.get(0), ev.target, ev.data.cal.get(0))) {
              if (ev.data.cal.data('colorpicker').onHide.apply(this, [ev.data.cal.get(0)]) !== false) {
                ev.data.cal.hide();
              }
              $(document).unbind('mousedown', hide);
            }
          };
          var isChildOf = function(parentEl, el, container) {
            if (parentEl === el) {
              return true;
            }
            if (parentEl.contains) {
              return parentEl.contains(el);
            }
            if (parentEl.compareDocumentPosition) {
              return !!(parentEl.compareDocumentPosition(el) & 16);
            }
            var prEl = el.parentNode;
            while (prEl && prEl !== container) {
              if (prEl === parentEl) { return true; }
              prEl = prEl.parentNode;
            }
            return false;
          };
          var getViewport = function() {
            var m = document.compatMode === 'CSS1Compat';
            return {
              l: window.pageXOffset || (m ? document.documentElement.scrollLeft : document.body.scrollLeft),
              t: window.pageYOffset || (m ? document.documentElement.scrollTop : document.body.scrollTop),
              w: window.innerWidth || (m ? document.documentElement.clientWidth : document.body.clientWidth),
              h: window.innerHeight || (m ? document.documentElement.clientHeight : document.body.clientHeight)
            };
          };
          var fixHSB = function(hsb) {
            return {
              h: Math.min(360, Math.max(0, hsb.h)),
              s: Math.min(100, Math.max(0, hsb.s)),
              b: Math.min(100, Math.max(0, hsb.b))
            };
          };
          var fixRGB = function(rgb) {
            return {
              r: Math.min(255, Math.max(0, rgb.r)),
              g: Math.min(255, Math.max(0, rgb.g)),
              b: Math.min(255, Math.max(0, rgb.b))
            };
          };
          var fixHex = function(hex) {
            var len = 6 - hex.length;
            if (len > 0) {
              var o = [];
              for (var i = 0; i < len; i++) {
                o.push('0');
              }
              o.push(hex);
              hex = o.join('');
            }
            return hex;
          };
          var HexToRGB = function(hex) {
            hex = parseInt(((hex.indexOf('#') > -1) ? hex.substring(1) : hex), 16);
            return { r: hex >> 16, g: (hex & 0x00FF00) >> 8, b: (hex & 0x0000FF) };
          };
          var HexToHSB = function(hex) {
            return RGBToHSB(HexToRGB(hex));
          };
          var RGBToHSB = function(rgb) {
            var hsb = {
              h: 0,
              s: 0,
              b: 0
            };
            var min = Math.min(rgb.r, rgb.g, rgb.b);
            var max = Math.max(rgb.r, rgb.g, rgb.b);
            var delta = max - min;
            hsb.b = max;
            hsb.s = max !== 0 ? 255 * delta / max : 0;
            if (hsb.s !== 0) {
              if (rgb.r === max) {
                hsb.h = (rgb.g - rgb.b) / delta;
              } else if (rgb.g === max) {
                hsb.h = 2 + (rgb.b - rgb.r) / delta;
              } else {
                hsb.h = 4 + (rgb.r - rgb.g) / delta;
              }
            } else {
              hsb.h = -1;
            }
            hsb.h *= 60;
            if (hsb.h < 0) {
              hsb.h += 360;
            }
            hsb.s *= 100 / 255;
            hsb.b *= 100 / 255;
            return hsb;
          };
          var HSBToRGB = function(hsb) {
            var rgb = {};
            var h = Math.round(hsb.h);
            var s = Math.round(hsb.s * 255 / 100);
            var v = Math.round(hsb.b * 255 / 100);
            if (s === 0) {
              rgb.r = rgb.g = rgb.b = v;
            } else {
              var t1 = v;
              var t2 = (255 - s) * v / 255;
              var t3 = (t1 - t2) * (h % 60) / 60;
              if (h === 360) h = 0;
              if (h < 60) { rgb.r = t1;	rgb.b = t2; rgb.g = t2 + t3; } else if (h < 120) { rgb.g = t1; rgb.b = t2;	rgb.r = t1 - t3; } else if (h < 180) { rgb.g = t1; rgb.r = t2;	rgb.b = t2 + t3; } else if (h < 240) { rgb.b = t1; rgb.r = t2;	rgb.g = t1 - t3; } else if (h < 300) { rgb.b = t1; rgb.g = t2;	rgb.r = t2 + t3; } else if (h < 360) { rgb.r = t1; rgb.g = t2;	rgb.b = t1 - t3; } else { rgb.r = 0; rgb.g = 0;	rgb.b = 0; }
            }
            return { r: Math.round(rgb.r), g: Math.round(rgb.g), b: Math.round(rgb.b) };
          };
          var RGBToHex = function(rgb) {
            var hex = [
              rgb.r.toString(16),
              rgb.g.toString(16),
              rgb.b.toString(16)
            ];
            $.each(hex, function(nr, val) {
              if (val.length === 1) {
                hex[nr] = '0' + val;
              }
            });
            return hex.join('');
          };
          var HSBToHex = function(hsb) {
            return RGBToHex(HSBToRGB(hsb));
          };
          var restoreOriginal = function() {
            var cal = $(this).parent();
            var col = cal.data('colorpicker').origColor;
            cal.data('colorpicker').color = col;
            fillRGBFields(col, cal.get(0));
            fillHexFields(col, cal.get(0));
            fillHSBFields(col, cal.get(0));
            setSelector(col, cal.get(0));
            setHue(col, cal.get(0));
            setNewColor(col, cal.get(0));
          };
          return {
            init: function(opt) {
              opt = $.extend({}, defaults, opt || {});
              if (typeof opt.color === 'string') {
                opt.color = HexToHSB(opt.color);
              } else if (opt.color.r !== undefined && opt.color.g !== undefined && opt.color.b !== undefined) {
                opt.color = RGBToHSB(opt.color);
              } else if (opt.color.h !== undefined && opt.color.s !== undefined && opt.color.b !== undefined) {
                opt.color = fixHSB(opt.color);
              } else {
                return this;
              }
              return this.each(function() {
                if (!$(this).data('colorpickerId')) {
                  var options = $.extend({}, opt);
                  options.origColor = opt.color;
                  var id = 'collorpicker_' + parseInt(Math.random() * 1000);
                  $(this).data('colorpickerId', id);
                  var cal = $(tpl).attr('id', id);
                  if (options.flat) {
                    cal.appendTo(this).show();
                  } else {
                    cal.appendTo(document.body);
                  }

                  cal.on('mousedown', function(e) {
                    e.stopPropagation();
                  });

                  options.fields = cal
                    .find('input')
                    .bind('keyup', keyDown)
                    .bind('change', change)
                    .bind('blur', blur)
                    .bind('focus', focus);
                  cal
                    .find('span').bind('mousedown', downIncrement).end()
                    .find('>div.colorpicker_current_color').bind('click', restoreOriginal);
                  options.selector = cal.find('div.colorpicker_color').bind('mousedown', downSelector);
                  options.selectorIndic = options.selector.find('div div');
                  options.el = this;
                  options.hue = cal.find('div.colorpicker_hue div');
                  cal.find('div.colorpicker_hue').bind('mousedown', downHue);
                  options.newColor = cal.find('div.colorpicker_new_color');
                  options.currentColor = cal.find('div.colorpicker_current_color');
                  cal.data('colorpicker', options);
                  cal.find('div.colorpicker_submit')
                    .bind('mouseenter', enterSubmit)
                    .bind('mouseleave', leaveSubmit)
                    .bind('click', clickSubmit);
                  fillRGBFields(options.color, cal.get(0));
                  fillHSBFields(options.color, cal.get(0));
                  fillHexFields(options.color, cal.get(0));
                  setHue(options.color, cal.get(0));
                  setSelector(options.color, cal.get(0));
                  setCurrentColor(options.color, cal.get(0));
                  setNewColor(options.color, cal.get(0));
                  if (options.flat) {
                    cal.css({
                      position: 'relative',
                      display: 'block'
                    });
                  } else {
                    $(this).bind(options.eventName, show);
                  }
                }
              });
            },
            showPicker: function() {
              return this.each(function() {
                if ($(this).data('colorpickerId')) {
                  show.apply(this);
                }
              });
            },
            hidePicker: function() {
              return this.each(function() {
                if ($(this).data('colorpickerId')) {
                  $('#' + $(this).data('colorpickerId')).hide();
                }
              });
            },
            setColor: function(col) {
              if (typeof col === 'string') {
                col = HexToHSB(col);
              } else if (col.r !== undefined && col.g !== undefined && col.b !== undefined) {
                col = RGBToHSB(col);
              } else if (col.h !== undefined && col.s !== undefined && col.b !== undefined) {
                col = fixHSB(col);
              } else {
                return this;
              }
              return this.each(function() {
                if ($(this).data('colorpickerId')) {
                  var cal = $('#' + $(this).data('colorpickerId'));
                  cal.data('colorpicker').color = col;
                  cal.data('colorpicker').origColor = col;
                  fillRGBFields(col, cal.get(0));
                  fillHSBFields(col, cal.get(0));
                  fillHexFields(col, cal.get(0));
                  setHue(col, cal.get(0));
                  setSelector(col, cal.get(0));
                  setCurrentColor(col, cal.get(0));
                  setNewColor(col, cal.get(0));
                }
              });
            }
          };
        }());
        $.fn.extend({
          ColorPicker: ColorPicker.init,
          ColorPickerHide: ColorPicker.hidePicker,
          ColorPickerShow: ColorPicker.showPicker,
          ColorPickerSetColor: ColorPicker.setColor
        });
      })(jQuery);
    }
  }
};
</script>

<style lang="scss" scoped>
html,
body {
  width: 100%;
  height: 100%;
}
.customize {
  height: 100vh;
  position: relative;
  overflow: hidden;
}
.shade{
  position: absolute;
  width: 100%;
  height: 100%;
  z-index: 10;
  top: 0;
  left: 0;
  background-color: rgba(0,0,0,0.5);
}
</style>
